package com.iplant.wms.serviceImpl.dao.brm;

import com.iplant.base.po.OutResult;
import com.iplant.base.utils.annotation.dao.DBBaseDAO;
import com.iplant.base.utils.general.StringUtils;
import com.iplant.base.utils.sql.BaseDAO;
import com.iplant.basic.service.po.bms.BMSEmployee;
import com.iplant.wms.service.basicenum.brm.BRMSerialItemTypes;
import com.iplant.wms.service.po.batch.MSSBatchRecord;
import com.iplant.wms.service.po.brm.BRMSerialNoCode;
import com.iplant.wms.service.po.brm.BRMSerialNoItem;
import com.iplant.wms.service.po.brm.BRMSerialNoRule;
import lombok.extern.slf4j.Slf4j;

import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@DBBaseDAO(BRMSerialNoCode.class)
@Slf4j
public class BRMSerialNoCodeDAO extends BaseDAO {

    private static BRMSerialNoCodeDAO Instance = null;

    public static BRMSerialNoCodeDAO getInstance() {
        if (Instance == null) {
            Instance = new BRMSerialNoCodeDAO();
        }
        return Instance;
    }

    public BRMSerialNoCodeDAO() {
        super("");
        this.Init();
    }


    public BRMSerialNoCode BCM_GetLastBarCode(BMSEmployee wLoginUser, BRMSerialNoRule wBCMRule, OutResult<Integer> wErrorCode) {
        Map<String, Object> wParams = new HashMap<>();
        wParams.put("RuleID", wBCMRule.ID);

        wParams.put("RuleString", wBCMRule.RuleString);


        return this.SelectPO(wLoginUser, wParams, wErrorCode);
    }

    public BRMSerialNoCode BCM_CreateBarCode(BMSEmployee wLoginUser, MSSBatchRecord wMSSBatchRecord, BRMSerialNoRule wBCMRule, OutResult<Integer> wErrorCode) {
        BRMSerialNoCode wBCMRuleCode = new BRMSerialNoCode();
        if (wMSSBatchRecord != null) {

            wBCMRule.CodeRuleString(wMSSBatchRecord.ProductDate, wMSSBatchRecord.MaterialNo, wMSSBatchRecord.FactoryCode, wMSSBatchRecord.CustomerCode);
        } else {
            wBCMRule.CodeRuleString( Calendar.getInstance(),"", "", "");
        }
        BRMSerialNoCode wLastRuleCode = this.BCM_GetLastBarCode(wLoginUser, wBCMRule, wErrorCode);
        if (wErrorCode.Result != 0) {
            return wBCMRuleCode;
        }
        String wLastBarCode = "";
        if (wLastRuleCode != null && wLastRuleCode.ID > 0){
            wLastBarCode = wLastRuleCode.Code;
            wMSSBatchRecord.Code=wLastBarCode;
        }
        return BCM_CreateBarCode(wLoginUser, wBCMRule, wLastBarCode, wErrorCode);
    }


    public BRMSerialNoCode BCM_CreateBarCode(BMSEmployee wLoginUser, BRMSerialNoRule wBCMRule, String wLastBarCode, OutResult<Integer> wErrorCode) {

        BRMSerialNoCode wBCMRuleCode = new BRMSerialNoCode();

        int wMaxNum = 0;

        if (wBCMRule.RuleItemList == null || wBCMRule.RuleItemList.size() == 0) {

            if (wBCMRule.SNLength <= 0 || wBCMRule.SNLength >= 10) {
                wBCMRule.SNLength = 7;
            }

            if (wBCMRule.RuleString == null) {
                wBCMRule.RuleString = "";
            }
            wBCMRule.RuleString = this.GetCodePrefix(wBCMRule.RuleString);

            if (wLastBarCode != null && StringUtils.isNotEmpty(wLastBarCode) && wLastBarCode.startsWith(wBCMRule.RuleString)) {
                wMaxNum = StringUtils.parseInt(wLastBarCode.substring(wBCMRule.RuleString.length()));
            }
            wBCMRuleCode.Code = StringUtils.Format("{0}{1}", wBCMRule.RuleString, String.format("%0" + wBCMRule.SNLength + "d", wMaxNum + 1));
        } else if (wLastBarCode == null || StringUtils.isEmpty(wLastBarCode)) {
            wBCMRuleCode.Code = wBCMRule.RuleString;
        } else {
            int wIndex = 0;
            for (BRMSerialNoItem wBCMRuleItem : wBCMRule.RuleItemList) {
                if (wBCMRuleItem == null)
                    continue;
                wIndex += wBCMRuleItem.Length;

                if (wBCMRuleItem.RuleItemType != BRMSerialItemTypes.Sequence.getValue())
                    continue;
                wBCMRule.SNLength = wBCMRuleItem.Length;
                wMaxNum = StringUtils.parseInt(wLastBarCode.substring(wIndex, wIndex + wBCMRuleItem.Length));
                break;
            }
            wBCMRuleCode.Code = wLastBarCode.substring(0, wIndex)
                    + String.format("%0" + wBCMRule.SNLength + "d", wMaxNum + 1)
                    + wLastBarCode.substring(wIndex + wBCMRule.SNLength);
        }

        wBCMRuleCode.RuleString = wBCMRule.RuleString;
        // wBCMRuleCode.Code = wBCMRule.LastBarCode;
        wBCMRuleCode.RuleID = wBCMRule.ID;
        this.UpdatePo(wLoginUser, wBCMRuleCode, wErrorCode);

        return wBCMRuleCode;
    }


    private String GetCodePrefix(String wCodePrefix) {
        String wResult = wCodePrefix;
        try {
            StringBuffer wStringBuffer = new StringBuffer("");

            Matcher wMatcher = Pattern.compile("\\{(?<Column>[^\\}]+)\\}", Pattern.CASE_INSENSITIVE).matcher(
                    wCodePrefix);

            Calendar wNow = Calendar.getInstance();

            while (wMatcher.find()) {
                wMatcher.appendReplacement(wStringBuffer, StringUtils.CalendarFormat(wNow, wMatcher.group("Column")));
            }
            wMatcher.appendTail(wStringBuffer);
            wResult = wStringBuffer.toString();
        } catch (Exception e) {
            log.error(e.toString());
        }
        return wResult;
    }


}
